# -*- coding: utf-8 -*-
"""
Created on Wed Apr  5 22:52:24 2023

@author: ASUS
"""

from PIL import Image
import time
import numpy as np
import matplotlib.pyplot as plt
import cv2
import warnings
warnings.filterwarnings('ignore')


# time1_start = time.time()



# 读取图像
img = Image.open('image.jpg')

# 转换为灰度图像
gray_img = img.convert('L')

# 转换为二维数组
img_array = np.array(gray_img)

# 绘制灰度直方图
plt.hist(img_array.flatten(), bins=256, range=(0, 255), density=True)
plt.show()


# time1_end = time.time()
# elapsed_time1 = round((time1_end-time1_start)*1000,3)
# print(elapsed_time1)


# time2_start = time.time()

# 读取图像
img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

# 添加椒盐噪声
noise_img1 = img.copy()
noise_num1 = int(img.shape[0]*img.shape[1]*0.05)  # 椒盐噪声的数量为图像像素数的 5%
for i in range(noise_num1):
    rand_x = np.random.randint(0, img.shape[0])
    rand_y = np.random.randint(0, img.shape[1])
    if np.random.randint(0, 2) == 0:
        noise_img1[rand_x, rand_y] = 0
    else:
        noise_img1[rand_x, rand_y] = 255

# 添加高斯噪声
noise_img2 = img.copy()
noise_num2 = int(img.shape[0]*img.shape[1]*0.05)  # 高斯噪声的数量为图像像素数的 5%
mean = 0
var = 100
sigma = var ** 0.5
gauss = np.random.normal(mean, sigma, (img.shape[0], img.shape[1]))
for i in range(noise_num2):
    rand_x = np.random.randint(0, img.shape[0])
    rand_y = np.random.randint(0, img.shape[1])
    noise_img2[rand_x, rand_y] += gauss[rand_x, rand_y]

# 计算信噪比
ps = np.sum(img ** 2) / img.size  # 原图像的功率
pn1 = np.sum((noise_img1 - img) ** 2) / img.size  # 加入椒盐噪声后的噪声功率
pn2 = np.sum((noise_img2 - img) ** 2) / img.size  # 加入高斯噪声后的噪声功率
snr1 = 10 * np.log10(ps / pn1)  # 加入椒盐噪声后的信噪比
snr2 = 10 * np.log10(ps / pn2)  # 加入高斯噪声后的信噪比

# 显示图像和信噪比
cv2.imshow('Original Image', img)
cv2.imshow('Salt and Pepper Noise Image', noise_img1)
cv2.imshow('Gaussian Noise Image', noise_img2)
print('Salt and Pepper Noise SNR:', snr1)
print('Gaussian Noise SNR:', snr2)
cv2.waitKey(0)
cv2.destroyAllWindows()

#保存椒盐噪声图片和高斯噪声图片
cv2.imwrite('Salt and Pepper Noise Image.jpg',noise_img1)
cv2.imwrite('Gaussian Noise Image.jpg',noise_img2)



# time2_end = time.time()
# elapsed_time2 = round((time2_end-time2_start)*1000,3)
# print(elapsed_time2)


# time3_start = time.time()



# # Sobel算子、Scharr算子、Canny算子和Laplacian算子。
# # 其中Sobel算子和Scharr算子都是基于图像的梯度计算，
# # Canny算子是一种广泛使用的基于边缘的检测算法，
# # 而Laplacian算子是一种基于图像的二阶导数计算。


# 读取未添加噪声的图像
img = cv2.imread('image.jpg', 0)

# 使用Sobel算子进行边缘检测
sobel_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
sobel_y = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
sobel = cv2.bitwise_or(sobel_x, sobel_y)

# 使用Scharr算子进行边缘检测
scharr_x = cv2.Scharr(img, cv2.CV_64F, 1, 0)
scharr_y = cv2.Scharr(img, cv2.CV_64F, 0, 1)
scharr = cv2.bitwise_or(scharr_x, scharr_y)

# 使用Canny算子进行边缘检测
canny = cv2.Canny(img, 100, 200)

# 使用Laplacian算子进行边缘检测
laplacian = cv2.Laplacian(img, cv2.CV_64F)

# 显示未添加噪声的图像和边缘检测结果
cv2.imshow('original_iamge', img)
cv2.imshow('sobel_image', sobel)
cv2.imshow('scharr_image', scharr)
cv2.imshow('canny_image', canny)
cv2.imshow('laplacian_image', laplacian)
cv2.waitKey(0)
cv2.destroyAllWindows()

#保存结果
cv2.imwrite('original_iamge.jpg',img)
cv2.imwrite('sobel_image.jpg', sobel)
cv2.imwrite('scharr_image.jpg', scharr)
cv2.imwrite('canny_image.jpg', canny)
cv2.imwrite('laplacian_image.jpg', laplacian)



# time3_end = time.time()
# elapsed_time3 = round((time3_end-time3_start)*1000,3)
# print(elapsed_time3)



# time4_start = time.time()


# 读取添加椒盐噪声的图像
img_pepper = cv2.imread('Salt and Pepper Noise Image.jpg', 0)

# 使用Sobel算子进行边缘检测
sobel_x_pepper = cv2.Sobel(img_pepper, cv2.CV_64F, 1, 0, ksize=5)
sobel_y_pepper = cv2.Sobel(img_pepper, cv2.CV_64F, 0, 1, ksize=5)
sobel_pepper = cv2.bitwise_or(sobel_x_pepper, sobel_y_pepper)

# 使用Scharr算子进行边缘检测
scharr_x_pepper = cv2.Scharr(img_pepper, cv2.CV_64F, 1, 0)
scharr_y_pepper = cv2.Scharr(img_pepper, cv2.CV_64F, 0, 1)
scharr_pepper = cv2.bitwise_or(scharr_x_pepper, scharr_y_pepper)

# 使用Canny算子进行边缘检测
canny_pepper = cv2.Canny(img_pepper, 100, 200)

# 使用Laplacian算子进行边缘检测
laplacian_pepper = cv2.Laplacian(img_pepper, cv2.CV_64F)

# 显示未添加噪声的图像和边缘检测结果
cv2.imshow('original_pepper', img_pepper)
cv2.imshow('sobel_pepper', sobel_pepper)
cv2.imshow('scharr_pepper', scharr_pepper)
cv2.imshow('canny_pepper', canny_pepper)
cv2.imshow('laplacian_pepper', laplacian_pepper)
cv2.waitKey(0)
cv2.destroyAllWindows()

#保存结果
cv2.imwrite('original_pepper.jpg',img_pepper)
cv2.imwrite('sobel_pepper.jpg', sobel_pepper)
cv2.imwrite('scharr_pepper.jpg', scharr_pepper)
cv2.imwrite('canny_pepper.jpg', canny_pepper)
cv2.imwrite('laplacian_pepper.jpg', laplacian_pepper)



# time4_end = time.time()
# elapsed_time4 = round((time4_end-time4_start)*1000,3)
# print(elapsed_time4)



# time5_start = time.time()



# 读取添加了高斯噪声的图像
img_noise = cv2.imread('Gaussian Noise Image.jpg', 0)

# 使用Sobel算子进行边缘检测
sobel_x_noise = cv2.Sobel(img_noise, cv2.CV_64F, 1, 0, ksize=5)
sobel_y_noise = cv2.Sobel(img_noise, cv2.CV_64F, 0, 1, ksize=5)
sobel_noise = cv2.bitwise_or(sobel_x_noise, sobel_y_noise)

# 使用Scharr算子进行边缘检测
scharr_x_noise = cv2.Scharr(img_noise, cv2.CV_64F, 1, 0)
scharr_y_noise = cv2.Scharr(img_noise, cv2.CV_64F, 0, 1)
scharr_noise = cv2.bitwise_or(scharr_x_noise, scharr_y_noise)

# 使用Canny算子进行边缘检测
canny_noise = cv2.Canny(img_noise, 100, 200)

# 使用Laplacian算子进行边缘检测
laplacian_noise = cv2.Laplacian(img_noise, cv2.CV_64F)

# 显示未添加噪声的图像和边缘检测结果
cv2.imshow('original_noise', img_noise)
cv2.imshow('sobel_noise', sobel_noise)
cv2.imshow('scharr_noise', scharr_noise)
cv2.imshow('canny_noise', canny_noise)
cv2.imshow('laplacian_noise', laplacian_noise)
cv2.waitKey(0)
cv2.destroyAllWindows()

#保存结果
cv2.imwrite('original_noise.jpg',img_noise)
cv2.imwrite('sobel_noise.jpg', sobel_noise)
cv2.imwrite('scharr_noise.jpg', scharr_noise)
cv2.imwrite('canny_noise.jpg', canny_noise)
cv2.imwrite('laplacian_noise.jpg', laplacian_noise)




# time5_end = time.time()
# elapsed_time5 = round((time5_end-time5_start)*1000,3)
# print(elapsed_time5)



# time6_start = time.time()




# 读入原始图像
img = cv2.imread('image.jpg', 0)
# 边缘检测
edges = cv2.Canny(img, 100, 200)
# 二值化
ret, binary_image = cv2.threshold(edges, 127, 255, cv2.THRESH_BINARY)
# 保存二值化图像
cv2.imwrite('binary_image.jpg', binary_image)



# time6_end = time.time()
# elapsed_time6 = round((time6_end-time6_start)*1000,3)
# print(elapsed_time6)



# time7_start = time.time()



# 读取二值化后的边缘图像
edge_img = cv2.imread("binary_image.jpg", cv2.IMREAD_GRAYSCALE)
# 统计边缘点数量
edge_pixels = cv2.countNonZero(edge_img)
# 统计总像素数
total_pixels = edge_img.shape[0] * edge_img.shape[1]
# 计算比例
edge_ratio = edge_pixels / total_pixels
print("边缘点占比：", edge_ratio)


# time7_end = time.time()
# elapsed_time7 = round((time7_end-time7_start)*1000,3)
# print(elapsed_time7)



